﻿using AutoMapper;
using crip.Common;
using crip.Dtos;
using crip.Helper;
using crip.Models;
using crip.ResourceParameters;
using crip.Services.IRepositorys;
using crip.Services.Repositorys;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Net.Http.Headers;
using System.Net.Mail;
using System.Security.Claims;
using System.Text.RegularExpressions;

namespace crip.Controllers
{
    /// <summary>
    /// 用户
    /// </summary>
    [Route("api/user")]
    [ApiController]
    public class UserController : ControllerBase
    {
        #region 依赖注入

        //缓存验证码
        private readonly IMemoryCache _cache;
        //使用HttpContext的接口
        private readonly IHttpContextAccessor _httpContextAccessor;
        //用户工具包
        private readonly UserManager<CripUser> _userManager;
        //AutoMapper 工具包
        private readonly IMapper _mapper;
        //用户仓库注入
        private IUserRepository _userRepository;
        //提供有关应用程序正在其中运行的 web 宿主环境的信息
        private readonly IWebHostEnvironment _webHostEnvironment;

        public UserController(
            UserManager<CripUser> userManager,
            IHttpContextAccessor httpContextAccessor,
            IMemoryCache cache,
            IMapper mapper,
            IUserRepository userRepository,
            IWebHostEnvironment webHostEnvironment

        )
        {
            _mapper = mapper;
            _httpContextAccessor = httpContextAccessor;
            _userManager = userManager;
            _cache = cache;
            _userRepository = userRepository;
            _webHostEnvironment = webHostEnvironment;
        }
        #endregion

        #region 单一资源CreateLinkForArea
        private IEnumerable<LinkDto> CreateLinkForUser()
        {
            var links = new List<LinkDto>();

            links.Add(
                new LinkDto(
                    Url.Link("GetUserMessage", null),
                    "self",
                    "GET"
                    )
                ); ;

            return links;
        }
        #endregion

        #region 发送注册邮件
        /// <summary>
        /// 发送注册邮件
        /// </summary>
        /// <param name="Email">邮箱</param>
        /// <returns></returns>
        [HttpPost("{Email}/Register")]
        public async Task<IActionResult> SendEmailToRegister(
            [FromRoute] string Email
         )
        {
            #region 校验
            PagesResponse pagesResponse = new PagesResponse();
            var user = await _userManager.FindByEmailAsync(Email);
            if (user != null)
            {
                pagesResponse.BadRequest("该邮箱已被注册");
                return BadRequest(pagesResponse);
            }
            if (Email == null)
            {
                pagesResponse.BadRequest("邮箱为空");
                return BadRequest(pagesResponse);   
            }
            #endregion

            #region 生成并设置验证码
            _cache.Remove(Email);//先清除上次的验证码

            Random random = new Random();
            string code = random.Next(100000, 999999).ToString();//生成随机数100000~999999

            var cacheEntryOptions = new MemoryCacheEntryOptions()
            .SetAbsoluteExpiration(TimeSpan.FromMinutes(3));//设置缓存时间（三分钟）单位是毫秒

            _cache.Set(Email, code, cacheEntryOptions); //服务端缓存邮箱的验证码通过cacheEntryOptions设置
                                                        //  MailMessage mail = EmailHelper.EmailValidationMessage(code); 

            #endregion

            #region 发送验证码
            EmailHelper.SetMessage("Closed regional integration platform","您正在申请注册CRIP，您的验证码是："+code+"，三分钟内有效",Email);
            if( !await EmailHelper.SendEmail())
            {
                pagesResponse.BadRequest("发送失败");
                return BadRequest(pagesResponse);
            }
            #endregion
            
            pagesResponse.Success("发送成功");
            return Ok(pagesResponse);

        }
        #endregion

        #region 发送重置密码邮件
        /// <summary>
        /// 发送重置密码邮件
        /// </summary>
        /// <param name="Email">邮箱</param>
        /// <returns></returns>
        [HttpPost("{Email}/Password")]
        public async Task<IActionResult> SendEmailToChangePassword(
            [FromRoute] string Email
         )
        {
            PagesResponse pagesResponse = new PagesResponse();
            #region 校验
            if (Email == null)
            {
                pagesResponse.BadRequest("邮箱为空");
                return BadRequest(pagesResponse);
            }
            #endregion

            #region 生成并设置验证码
            //随机数类
            Random random = new Random();
            string code = random.Next(100000, 999999).ToString();//生成随机数100000~999999

            _cache.Remove(Email);//先清除上次的验证码

            var cacheEntryOptions = new MemoryCacheEntryOptions()
            .SetAbsoluteExpiration(TimeSpan.FromMinutes(3));//设置缓存时间（三分钟）单位是毫秒

            _cache.Set(Email, code, cacheEntryOptions); //服务端缓存邮箱的验证码通过cacheEntryOptions设置
                                                        //  MailMessage mail = EmailHelper.EmailValidationMessage(code); 
            #endregion

            #region 发送邮件
            EmailHelper.SetMessage("Closed regional integration platform", "您正在申请修改CRIP的密码，您的验证码是："+code+"，三分钟内有效", Email);
            if (!await EmailHelper.SendEmail())
            {
                pagesResponse.BadRequest("发送失败");
                return BadRequest(pagesResponse);
            }
            #endregion

            pagesResponse.Success("发送成功");
            return Ok(pagesResponse);
        }
        #endregion

        #region 获得用户信息
        /// <summary>
        /// 获得用户信息
        /// </summary>
        /// <param name="mediaType"></param>
        /// <returns></returns>
        [Produces(
            "application/json",
            "application/vnd.crip.hateoas+json",
            "application/vnd.crip.User.simplify+json",
            "application/vnd.crip.User.simplify.hateoas+json"
            )]
        [HttpGet(Name = "GetUserMessage")]
        [Authorize(AuthenticationSchemes = "Bearer")]
        public async Task<IActionResult> GetUserMessage(
            [FromHeader(Name = "Accept")] string mediaType
          )
        {
            
            PagesResponse pagesResponse = new PagesResponse(); 

            //获取媒体类型
            if (!MediaTypeHeaderValue
               .TryParse(mediaType, out MediaTypeHeaderValue parsedMediatype))
            {
                pagesResponse.BadRequest("未查找到媒体类型");
                return BadRequest(pagesResponse);
            }
            //获取user
            var userId = _httpContextAccessor.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value;
            var user = await _userManager.FindByIdAsync(userId);
            if (user == null)
            {
                pagesResponse.NotFound("未找到用户");
                return NotFound(pagesResponse);
             }
         
            #region 媒体资源类型获取
            //截取是否hateoas请求
            bool isHateoas = parsedMediatype.SubTypeWithoutSuffix
                .EndsWith("hateoas", StringComparison.InvariantCultureIgnoreCase);
            //截取主要请求的媒体类型
            var primaryMediaType = isHateoas
                ? parsedMediatype.SubTypeWithoutSuffix
                    .Substring(0, parsedMediatype.SubTypeWithoutSuffix.Length - 8)
                : parsedMediatype.SubTypeWithoutSuffix;
            object usersDto;
            #endregion
            Console.WriteLine(primaryMediaType);
            if(primaryMediaType == "vnd.crip.User.simplify")
            {
                usersDto = _mapper.Map<UserSimplifyDto>(user);
            }
            else
            {
                usersDto = _mapper.Map<UserDto>(user);
            }

            if (isHateoas)
            {
                var hateoasLinks = CreateLinkForUser();
                var hateoasRes = new
                {
                    userMessage = usersDto,
                    Links = hateoasLinks
                };
                pagesResponse.Success(hateoasRes);
            }
            else
            {
                var Res = new
                {
                    userMessage = usersDto,
                };
                pagesResponse.Success(Res);
            }
            return Ok(pagesResponse);

        }
        #endregion

        #region 实名认证 
        /// <summary>
        /// 实名认证
        /// </summary>
        /// <returns></returns>
        
        [HttpPost("RealName")]
        [Authorize(AuthenticationSchemes = "Bearer")]
        public async Task<IActionResult> RealNameAuthentication(
            [FromBody] RealNameParameters realNameParameters)
        {
            PagesResponse pagesResponse = new PagesResponse();

            var userId = _httpContextAccessor.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier);
            var user =await _userManager.FindByIdAsync(userId);
            var rootPath = _webHostEnvironment.ContentRootPath;
            string frontfilePath = rootPath + $@"\Static\Upload\RealName\Front-{userId}.jpg";
            string backfilePath = rootPath + $@"\Static\Upload\RealName\Back-{userId}.jpg";

            #region 校验
            if (user == null)
            {
                pagesResponse.BadRequest("用户不存在");
                return BadRequest(pagesResponse);
            }
      
            //身份证正面图片
            if (!System.IO.File.Exists(frontfilePath))
            {
                pagesResponse.BadRequest("请上传身份证正面图片");
                return BadRequest(pagesResponse);
            }
            //身份证反面图片
            if (!System.IO.File.Exists(backfilePath))
            {
                pagesResponse.BadRequest("请上传身份证反面图片");
                return BadRequest(pagesResponse);
            }

            //身份证号码
            Regex regexId = new Regex(@"^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$");
            if (!regexId.IsMatch(realNameParameters.RealID))
            {
                pagesResponse.BadRequest("身份证号码格式不正确");
                return BadRequest(pagesResponse);
            }
            //姓名
            Regex regexName = new Regex(@"^[\u4e00-\u9fa5]{2,6}$");
            if (!regexName.IsMatch(realNameParameters.RealName))
            {
                pagesResponse.BadRequest("身份证姓名格式不正确");
                return BadRequest(pagesResponse);
            }
            //手机号|座机号
            Regex regexPhoneNumber = new Regex(@"^\d{7,11}$");
            if (!regexPhoneNumber.IsMatch(realNameParameters.PhoneNumber))
            {
                pagesResponse.BadRequest("电话号码格式不正确");
                return BadRequest(pagesResponse);
            }
            #endregion

            #region 正常存储
            user.PhoneNumber = realNameParameters.PhoneNumber;
            user.PhoneNumberConfirmed = true;
            user.Address = realNameParameters.Address;
            #endregion

            #region 七牛云转储
            qiniu_imgHelper _ImgHelper = new qiniu_imgHelper();
            string frontUrl = _ImgHelper.FileUpload($@"Front-{userId}.jpg", frontfilePath);
            string backUrl = _ImgHelper.FileUpload($@"Back-{userId}.jpg", backfilePath);

            var frontUrlRes = @"http://rbi2o3c3v.hb-bkt.clouddn.com/" + frontUrl;
            var backUrlRes = @"http://rbi2o3c3v.hb-bkt.clouddn.com/" + backUrl;
            #endregion

            #region 加密存储
           // RSAHelper rSAHelper = new RSAHelper();
            user.RealName = RSAHelper.RSAEncryption(realNameParameters.RealName,userId);//以用户userId为密钥容器,加密真实姓名
            user.RealID = RSAHelper.RSAEncryption(realNameParameters.RealID, userId);   //以用户userId为密钥容器,加密真实身份证号码
            user.frontIDCardUrl = RSAHelper.RSAEncryption(frontUrlRes,userId);          //以用户userId为密钥容器,加密身份证正面照片
            user.backIDCardUrl = RSAHelper.RSAEncryption(backUrlRes, userId);           //以用户userId为密钥容器,加密身份证反面照片
            #endregion

            System.IO.File.Delete(frontfilePath);
            System.IO.File.Delete(backfilePath);

            await _userRepository.SaveAsync();
            pagesResponse.Success("实名成功");
            return Ok(pagesResponse);
        }
        #endregion

        #region 上传身份证正反面图片
        /// <summary>
        /// 上传身份证正反面图片
        /// </summary>
        /// <returns>状态码</returns>
        [Produces("application/vnd.crip.Front+json",
                  "application/vnd.crip.Back+json"
         )]
        [HttpPost("RealName/upload")]
        [Authorize(AuthenticationSchemes = "Bearer")]
        public async Task<IActionResult> UploadPictureToRealName(
        [FromHeader(Name = "Accept")] string mediaType)
        {
            PagesResponse pagesResponse = new PagesResponse();
            var useId = _httpContextAccessor.HttpContext?.User.FindFirstValue(ClaimTypes.NameIdentifier);

            if (!MediaTypeHeaderValue
            .TryParse(mediaType, out MediaTypeHeaderValue parsedMediatype))
            {
                pagesResponse.BadRequest("未查找到媒体类型");
                return BadRequest(pagesResponse);
            }

            IFormFile formFile = Request.Form.Files[0];
            if (formFile != null)
            {
                var rootPath = _webHostEnvironment.ContentRootPath;

                string formFileName = formFile.FileName; //文件全名
                string FileType = formFileName.Substring(formFileName.LastIndexOf('.')); //截取文件类型
                Console.WriteLine(FileType);
                if (FileType!=".jpg")
                {
                    pagesResponse.BadRequest("请上传jpg格式的图片");
                    return BadRequest(pagesResponse);
                }
                //文件名称

                //截取主要请求的媒体类型查看上传正面还是反面
                var primaryMediaType = parsedMediatype.SubTypeWithoutSuffix.Substring(9);
                string projectFileName = "";
                string type = "";
                if (primaryMediaType.Equals("Front"))
                {
                projectFileName = "Front-"+  useId +  FileType;
                    type = "Front";
                }
                else
                {
                projectFileName = "Back-"+  useId +  FileType;
                    type ="Back";
                }

                string uploadPath = rootPath + @"\Static\Upload\RealName";

                if (!Directory.Exists(uploadPath))
                {
                    Directory.CreateDirectory(uploadPath);
                }
                //上传的文件的路径
                string filePath = rootPath + $@"\Static\Upload\RealName\{projectFileName}";

                using (FileStream fs = System.IO.File.Create(filePath))
                {
                    formFile.CopyTo(fs);
                    fs.Flush();
                }

                await _userRepository.SaveAsync();

                pagesResponse.Success("上传成功");
                return Ok(pagesResponse);
            }
            else
            {
                pagesResponse.BadRequest("上传失败");
                return BadRequest(pagesResponse);
            }
        }
        #endregion


    }
}
